module analyzer_generator 
(

	// Logic analyzer probe ports:
	input          p00,		// Connected to SignalTap only
	input          p10,		// Connected to SignalTap only
	input          p20,		// Connected to SignalTap only
	input          p30,		// Connected to SignalTap only
	input          p40,		// Connected to SignalTap only

	input          p01,		// Connected to SignalTap only
	input          p11,		// Connected to SignalTap only
	input          p21,		// Connected to SignalTap only
	input          p31,		// Connected to SignalTap only
	input          p41,		// Connected to SignalTap only

	// Signal generator output ports:
	output          s00,
	output          s10,
	output          s20,
	output          s30,
	output          s40,

	output          s01,
	output          s11,
	output          s21,
	output          s31,
	output          s41,


	input          pll_ref_clk

);

	`define     GENERATOR_OUTPUT_WIDTH 10	
	`define		RAM_PATTERN_ADDR_WIDTH	10 /* Equivalent to 2^10=1024 words deep*/
	
	wire												select_counter;
	wire												select_issp;
	wire												select_ram;
	
	reg   [`GENERATOR_OUTPUT_WIDTH-1:0]		generator_out_reg;
	
	reg	[`GENERATOR_OUTPUT_WIDTH-1:0]		counter_reg;
	wire	[`GENERATOR_OUTPUT_WIDTH-1:0]		issp_pattern_source;
	wire	[`GENERATOR_OUTPUT_WIDTH-1:0]		ram_pattern_source;

	wire												ram_pattern_start;			// Reset addr to be 0 upon a restart
	reg												ram_pattern_start_reg;
	wire												ram_pattern_loop_around;
	reg	[`RAM_PATTERN_ADDR_WIDTH-1:0]		ram_pattern_addr_reg;
	reg												ram_pattern_addr_reset_reg;
	
	
	wire			clk;
	
	assign clk = pll_ref_clk;

	// Select which pattern generator to use with the In-System Source and Probe tool
	altsource_probe
	#(
		.probe_width(0),
		.source_width(3)
	) 
	pattern_geneator_selection
	(
		.source({select_counter, select_issp, select_ram})
	);
	
	initial
		generator_out_reg <= `GENERATOR_OUTPUT_WIDTH'b0;
	always @ (posedge clk)
		if ( select_counter )
			generator_out_reg <= counter_reg;
		else if ( select_issp )
			generator_out_reg <= issp_pattern_source;
		else if ( select_ram )
			generator_out_reg <= ram_pattern_source;
		else
			generator_out_reg <= `GENERATOR_OUTPUT_WIDTH'b0;
			
	assign {s00, s01, s10, s11, s20, s21, s30, s31, s40, s41} = generator_out_reg;
	
	// Counter pattern generator:
	initial
		counter_reg <= `GENERATOR_OUTPUT_WIDTH'b0;
	always @ (posedge clk)
		counter_reg <= counter_reg + `GENERATOR_OUTPUT_WIDTH'b1;
		
	// Slow pattern generation by the In-System Source and Probe tool
	altsource_probe
	#(
		.probe_width(0),
		.source_width(`GENERATOR_OUTPUT_WIDTH)
	)
	issp_pattern_geneator
	(
		.source(issp_pattern_source)
	);
	
	// At-speed custom pattern output as stored in internal ram.
	//
	// The ram content can be loaded using the In-System Memory Content Editor tool
	// An initial ram content can also be defined using INIT_FILE parameter.  See the megafunction spec.
	altsyncram
	#(
		.OPERATION_MODE("SINGLE_PORT"),
		.WIDTH_A(`GENERATOR_OUTPUT_WIDTH),
		.WIDTHAD_A(`RAM_PATTERN_ADDR_WIDTH),
		.ENABLE_RUNTIME_MOD("YES"),
		.INSTANCE_NAME("PATN")
	)
	ram_pattern_storage
	(
		.clock0(clk),
		.address_a(ram_pattern_addr_reg),
		.q_a(ram_pattern_source)
	);
	
	// Control the ram pattern generator using the In-System Source and Probe tool
	altsource_probe
	#(
		.probe_width(0),
		.source_width(2)
	) 
	ram_pattern_geneator_control
	(
		.source({ram_pattern_start, ram_pattern_loop_around})
	);
	
	// Create a reset pulse 
	initial
		ram_pattern_start_reg <= 1'b0;
	always @ (posedge clk)
		ram_pattern_start_reg <= ram_pattern_start;
		
	initial
		ram_pattern_addr_reset_reg <= 1'b0;
	always @ (posedge clk)
		if ( !ram_pattern_start_reg && ram_pattern_start )
			ram_pattern_addr_reset_reg <= 1'b1;
		else if ( ram_pattern_addr_reset_reg )
			ram_pattern_addr_reset_reg <= 1'b0;
			
	initial
		ram_pattern_addr_reg <= `RAM_PATTERN_ADDR_WIDTH'b0;
	always @ (posedge clk)
		if ( ram_pattern_addr_reset_reg )
			ram_pattern_addr_reg <= `RAM_PATTERN_ADDR_WIDTH'b0;
		else if ( ram_pattern_start && 
		          ( ram_pattern_loop_around || 
					   ( !ram_pattern_loop_around && 
						  !(&(ram_pattern_addr_reg & {`RAM_PATTERN_ADDR_WIDTH{1'b1}})))))
				ram_pattern_addr_reg <= ram_pattern_addr_reg + `RAM_PATTERN_ADDR_WIDTH'b1;
		
endmodule
